<?php

/**
 * 数据库管理控制器类
 * 
 * @package    01CMS
 * @subpackage admin
 * @author     rolong at vip.qq.com
 * @version    1.0.0
 * @link       http://www.01cms.com
 */

class DatabaseController extends Controller
{
    public $title = '数据库管理';
    private $outputNum = 0;

    function __construct ()
    {
        parent::__construct();
        
        if (! model('User')->isLogined())
        {
            redirect('admin/login');
        }
        
        if (! model('User')->checkAuth())
        {
            exit('您的权限不足');
        }
    }

    function backup ($action = '', $name = '')
    {
        $Model = model('Db');
        
        if ($action == "showCreate")
        {
            if ($name != '')
            {
                $Model->query("SHOW CREATE TABLE " . $this->Load->config['mysql']['database'] . "." . $name);
                $data = $Model->getNextRow(0, 'array', MYSQL_NUM);
                response('<pre>' . $data[1] . '</pre>');
            }
        }
        else if ($action == "optimize")
        {
            $status = $Model->query("OPTIMIZE TABLE `$name` ");
            response('优化成功：' . $name, '优化失败：' . $Model->getError(), $status);
        }
        else if ($action == "repair")
        {
            $status = $Model->query("REPAIR TABLE `$name` ");
            response('修复成功：' . $name, '修复失败：' . $Model->getError(), $status);
        }
        else
        {
            $this->title .= ' => 数据备份';
            $tableArray = $this->Load->post('selected');
            $rows = $Model->getRows('show tables', 0, 'array', MYSQL_NUM);
            $countRows = count($rows);
            for ($i = 0; $i < $countRows; $i ++)
            {
                $count = $Model->getRow("select count(*) as count from {$rows[$i][0]}");
                
                if (empty($tableArray['selected']))
                {
                    $checked = ereg("^{$this->Load->config['mysql']['prefix']}", $rows[$i][0]) ? 'checked="checked"' : '';
                }
                else
                {
                    $checked = in_array($rows[$i][0], $tableArray['selected']) ? 'checked="checked"' : '';
                }
                
                $left = array('name'=>$rows[$i][0], 'count'=>$count->count, 'checked'=>$checked);
                $i ++;
                if (isset($rows[$i][0]))
                {
                    $count = $Model->getRow("select count(*) as count from {$rows[$i][0]}");
                    if (empty($tableArray['selected']))
                    {
                        $checked = ereg("^{$this->Load->config['mysql']['prefix']}", $rows[$i][0]) ? 'checked="checked"' : '';
                    }
                    else
                    {
                        $checked = in_array($rows[$i][0], $tableArray['selected']) ? 'checked="checked"' : '';
                    }
                    $right = array('name'=>$rows[$i][0], 'count'=>$count->count, 'checked'=>$checked);
                }
                else
                {
                    $right = array('name'=>'');
                }
                $tables[] = array('left'=>$left, 'right'=>$right);
            }
            $this->tables = $tables;
            $this->Load->view('smarty');
            
            if ($action == "backup" && ! empty($tableArray['selected']))
            {
                $this->output('getDialog("","top");', FALSE);
                ini_set('max_execution_time', 0);
                ob_implicit_flush(1);
                $backupDir = APP_PATH . '/data/backup';
                clearDirs($backupDir);
                $this->output('备份目录：' . $backupDir);
                $backupFile = $backupDir . "/tables_struct_" . substr(md5(time() . mt_rand(1000, 5000)), 0, 16) . ".sql";
                $fp = fopen($backupFile, "w");
                
                foreach ($tableArray['selected'] as $table)
                {
                    fwrite($fp, "DROP TABLE IF EXISTS `$table`;\r\n\r\n");
                    $Model->query("SHOW CREATE TABLE " . $this->Load->config['mysql']['database'] . "." . $table, 0, 'array', MYSQL_BOTH);
                    $row = $Model->getNextRow(0, 'array', MYSQL_NUM);
                    $tableStruct = eregi_replace("AUTO_INCREMENT=([0-9]{1,})[ \r\n\t]{1,}", "", $row[1]);
                    fwrite($fp, '' . $tableStruct . ";\r\n\r\n");
                }
                
                fclose($fp);
                $this->output('成功备份：数据库' . $this->Load->config['mysql']['database'] . '的表结构');
                
                foreach ($tableArray['selected'] as $table)
                {
                    $fields = $backupString = '';
                    $intable = "INSERT INTO `{$table}` VALUES(";
                    $fieldsResource = mysql_list_fields($this->Load->config['mysql']['database'], $table, $Model->linkId);
                    $j = 0;
                    while ($fieldObject = mysql_fetch_field($fieldsResource))
                    {
                        $fields[$j] = trim($fieldObject->name);
                        $j ++;
                    }
                    $fieldsD = $j - 1;
                    $fileCount = 0;
                    $Model->query("Select * From `{$table}` ");
                    while ($backupData = $Model->getNextRow(0, 'array'))
                    {
                        $line = $intable;
                        for ($j = 0; $j <= $fieldsD; $j ++)
                        {
                            if ($j < $fieldsD)
                            {
                                $line .= "'" . $this->replaceLine(addslashes($backupData[$fields[$j]])) . "',";
                            }
                            else
                            {
                                $line .= "'" . $this->replaceLine(addslashes($backupData[$fields[$j]])) . "');\r\n";
                            }
                        }
                        $backupString .= $line;
                        if (strlen($backupString) > 2097152)
                        {
                            $backupFile = "{$backupDir}/{$table}_{$fileCount}_" . substr(md5(time() . mt_rand(1000, 5000)), 0, 16) . ".sql";
                            $fp = fopen($backupFile, "w");
                            fwrite($fp, $backupString);
                            fclose($fp);
                            $fileCount ++;
                            $backupString = '';
                        }
                    }
                    
                    if ($backupString != '')
                    {
                        $backupFile = "{$backupDir}/{$table}_{$fileCount}_" . substr(md5(time() . mt_rand(1000, 5000)), 0, 16) . ".sql";
                        $fp = fopen($backupFile, "w");
                        fwrite($fp, $backupString);
                        fclose($fp);
                    }
                    
                    $this->output("成功备份：{$table}");
                    sleep(1);
                }
                
                $this->output('所选数据备份完毕！');
            
            }
        }
    }

    function revert ($action = '')
    {
        $this->title .= ' => 数据还原';
        $tableArray = $this->Load->post('selected,struct,del');
        if (empty($tableArray['selected']))
        {
            $this->structChecked = 'checked="checked"';
            $this->delChecked = 'checked="checked"';
        }
        else
        {
            $this->structChecked = empty($tableArray['struct']) ? '' : 'checked="checked"';
            $this->delChecked = empty($tableArray['del']) ? '' : 'checked="checked"';
        }
        $rows = Array();
        $backupDir = APP_PATH . '/data/backup';
        $dh = dir($backupDir);
        $this->structFile = '';
        while (($fileName = $dh->read()) !== false)
        {
            if (! ereg('sql$', $fileName))
            {
                continue;
            }
            
            if (ereg('tables_struct', $fileName))
            {
                $this->structFile = $fileName;
            }
            else if (filesize("{$backupDir}/{$fileName}") > 0)
            {
                $rows[] = $fileName;
            }
        }
        $dh->close();
        
        $countRows = count($rows);
        
        for ($i = 0; $i < $countRows; $i ++)
        {
            if (empty($tableArray['selected']))
            {
                $checked = ereg("^{$this->Load->config['mysql']['prefix']}", $rows[$i]) ? 'checked="checked"' : '';
            }
            else
            {
                $checked = in_array($rows[$i], $tableArray['selected']) ? 'checked="checked"' : '';
            }
            
            $left = array('name'=>$rows[$i], 'checked'=>$checked);
            $i ++;
            if (isset($rows[$i]))
            {
                if (empty($tableArray['selected']))
                {
                    $checked = ereg("^{$this->Load->config['mysql']['prefix']}", $rows[$i]) ? 'checked="checked"' : '';
                }
                else
                {
                    $checked = in_array($rows[$i], $tableArray['selected']) ? 'checked="checked"' : '';
                }
                $right = array('name'=>$rows[$i], 'checked'=>$checked);
            }
            else
            {
                $right = array('name'=>'');
            }
            $tables[] = array('left'=>$left, 'right'=>$right);
        }
        
        $this->tables = empty($tables) ? array() : $tables;
        $this->Load->view('smarty');
        
        if ($action == 'revert')
        {
            $this->output('getDialog("","top");', FALSE);
            ini_set('max_execution_time', 0);
            ob_implicit_flush(1);
            $this->output('开始还原...');
            $Model = model('Db');
            if (! empty($tableArray['struct']))
            {
                $sql = '';
                $fp = fopen("{$backupDir}/{$tableArray['struct']}", 'r');
                while (! feof($fp))
                {
                    $sql .= fgets($fp, 1024);
                }
                fclose($fp);
                $querys = explode(';', $sql);
                
                foreach ($querys as $query)
                {
                    if (trim($query) != '')
                    {
                        $Model->query(trim($query) . ';');
                    }
                }
                if (! empty($tableArray['del']))
                {
                    @unlink("{$backupDir}/{$tableArray['struct']}");
                }
                
                $this->output("成功还原：表结构信息({$tableArray['struct']})");
            }
            
            foreach ($tableArray['selected'] as $table)
            {
                $ok = 0;
                if (filesize("{$backupDir}/$table") > 0)
                {
                    $fp = fopen("{$backupDir}/$table", 'r');
                    while (! feof($fp))
                    {
                        $line = trim(fgets($fp, 512 * 1024));
                        if ($line == "")
                        {
                            continue;
                        }
                        $status = $Model->query($line);
                        if ($status)
                        {
                            $ok ++;
                        }
                    }
                    fclose($fp);
                }
                
                if (! empty($tableArray['del']))
                {
                    @unlink("{$backupDir}/{$table}");
                }
                
                $this->output("成功还原：{$table}({$ok}条记录)");
                sleep(1);
            }
            
            $this->output('所选数据还原完毕！');
        }
    }

    private function output ($info, $updateHtml = true)
    {
        if ($updateHtml)
        {
            if ($this->outputNum > 0)
            {
                echo '<script>$(".ui-dialog-message").append("<br />' . $info . '");</script>';
            }
            else
            {
                echo '<script>$(".ui-dialog-message").html("' . $info . '");</script>';
            }
            
            $this->outputNum = $this->outputNum + 1;
        }
        else
        {
            echo '<script>' . $info . '</script>';
        }
        @ob_flush();
        @flush();
    }

    private function replaceLine ($str)
    {
        $str = str_replace("\r", '\r', $str);
        $str = str_replace("\n", '\n', $str);
        return $str;
    }
}

/* End of file /01CMS/application/controller/SettingController.php */